package com.chixing.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chixing.commons.ServerResponse;
import com.chixing.mapper.AddressMapper;
import com.chixing.mapper.MyorderDetailMapper;
import com.chixing.mapper.MyorderMapper;
import com.chixing.mapper.ProductMapper;
import com.chixing.pojo.Address;
import com.chixing.pojo.Myorder;
import com.chixing.pojo.MyorderDetail;
import com.chixing.pojo.Product;
import com.chixing.service.IMyorderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xiaotao
 * @since 2022-10-12
 */
@Service
public class MyorderServiceImpl implements IMyorderService {

    @Autowired
    private MyorderMapper myorderMapper;

    @Autowired
    private AddressMapper addressMapper;

    @Autowired
    private MyorderDetailMapper detailMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private DefaultRedisScript<Long> script;

    //调用 lua脚本
    @PostConstruct
    public void init(){
        script = new DefaultRedisScript<>(); //实例化一个脚本对象 script
        script.setResultType(Long.class);
        script.setScriptSource(new ResourceScriptSource(new ClassPathResource("niceyoo.lua")));
    }

    @Override
    public ServerResponse saveMyOrder(Myorder myorder) {
        int rows = myorderMapper.insert(myorder);
        if(rows>0)
            return ServerResponse.success("添加订单成功",true);
        else
            return ServerResponse.fail("添加订单失败",false);
    }

    @Override
    public ServerResponse updateMyorder(Myorder myorder) {
        int rows = myorderMapper.updateById(myorder);
        if(rows>0)
            return ServerResponse.success("修改订单成功",true);
        else
            return ServerResponse.fail("修改订单失败",false);
    }

    @Override
    public ServerResponse getById(Integer myorderId) {

        return ServerResponse.success("查询订单成功",myorderMapper.selectById(myorderId));
    }

    @Override
    public List<Myorder> getAllOrderById(Integer userId) {
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("user_id",userId);
        List<Myorder> myorderList = myorderMapper.selectList(wrapper);
        return myorderList;
    }

    @Override
    public Myorder selectById(Integer myorderId) {
        Myorder myorder = myorderMapper.selectById(myorderId);
        return myorder;
    }

    /* 我的订单页 */
    //全部订单：不查 4
    @Override
    public ServerResponse getAll(Integer userId) {
        List<Object> list = new ArrayList<>();

        //1.根据 userId 查询 myorder表，返回 list集合 【大订单】
        QueryWrapper<Myorder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId).ne("myorder_status",3); //3：已删除的不查
        List<Myorder> myorders = myorderMapper.selectList(queryWrapper);
        System.out.println("大订单：" + myorders);

        if(myorders != null){
            for (Myorder order: myorders){
                Map<String,Object> map = new HashMap<>();
                map.put("订单id",order.getMyorderId());
                map.put("下单时间",order.getMyorderCreateTime());
                map.put("订单号",order.getMyorderNumber());

                Integer status = order.getMyorderStatus();
                String orderStatus = null;
                if(status == 0) orderStatus = "待付款";
                else if(status == 1) orderStatus = "已完成";
                else if(status == 2) orderStatus = "已取消";

                map.put("订单状态",orderStatus);
                map.put("订单金额",order.getMyorderPrice());

                //2.根据大订单对象的 addressId 查询 address表，返回 Address对象，获取 addressName
                Address address = addressMapper.selectById(order.getAddressId());
                System.out.println("收件人：" + address);
                map.put("地址id",order.getAddressId());
                map.put("收件人",address.getAddressName());

                //3.根据大订单对象的 myorderId 条件查询 myorder_detail表，返回订单详情对象 【小订单】
                QueryWrapper<MyorderDetail> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("myorder_id",order.getMyorderId());
                MyorderDetail detail = detailMapper.selectOne(queryWrapper1);
                System.out.println("小订单:" + detail);
                map.put("共几单",1); //小订单个数 1

                //4.获取商品信息
                Product product = productMapper.selectById(detail.getProductId());
                System.out.println("商品：" + product);
                map.put("商品名称",product.getProductName());
                map.put("商品主图片",product.getProductMainImg());
                list.add(map);
            }
            return ServerResponse.success("成功获取到订单数据！",list);
        }else
            return ServerResponse.fail("该用户暂无订单！",null);
    }

    //状态修改
    @Override
    public int updateOrderStatus(String orderNum) {
        QueryWrapper<Myorder> wrapper = new QueryWrapper<>();
        wrapper.eq("myorder_number",orderNum);
        Myorder myorder = myorderMapper.selectOne(wrapper);
        if(myorder.getMyorderStatus() == 0) { //待付款 0 ---取消订单--> 已取消 2
            myorder.setMyorderStatus(2);

            //redis 中商品数 +1
            QueryWrapper<MyorderDetail> wrapper1 = new QueryWrapper<>();
            wrapper1.eq("myorder_id",myorder.getMyorderId());
            MyorderDetail detail = detailMapper.selectOne(wrapper1);
            plusRedisCount(detail.getProductId());
        }

        else if(myorder.getMyorderStatus() == 1) //已完成 1 ---删除--> 已删除 3
            myorder.setMyorderStatus(3);
        else if(myorder.getMyorderStatus() == 2) //已取消 2 ---删除--> 已删除 3
            myorder.setMyorderStatus(3);
        return myorderMapper.updateById(myorder);
    }

    //取消订单，redis库存 +1
    public void plusRedisCount(Integer proId){

        //1.先获取商品，如果存在，直接 +1
        String idStr = String.valueOf(proId);
        String dataKey = "pro_" + idStr;
        Product product = (Product)redisTemplate.opsForValue().get(dataKey);
        if(product != null){

            //2.操作前设置标记变量 lock（上锁）
            String uuid = UUID.randomUUID().toString().replace("-",""); //uuid：保证一人一把锁
            Boolean flag = redisTemplate.opsForValue().setIfAbsent("lock",uuid,5, TimeUnit.SECONDS); //设置锁的过期时间 5s > 业务处理时间，保证如果业务异常，一直未释放锁，就让锁自动释放。（避免死锁）
            System.out.println("上锁是否成功：" + flag);

            if(flag){
                System.out.println(Thread.currentThread().getName() + "获得了锁" + redisTemplate.opsForValue().get("lock"));

                //库存 +1
                Integer afterCount = product.getProductCount() + 1;
                product.setProductCount(afterCount);
                redisTemplate.opsForValue().set(dataKey,product);
                System.out.println("====================已完成库存+1！");

                //3.利用 lua脚本，删除锁（原子性：只能删自己的锁）
                Long execute = redisTemplate.execute(script, Arrays.asList("lock"),uuid);
                System.out.println(Thread.currentThread().getName() + "execute执行结果，1表示执行del，0表示未执行 ===================>" + execute);

            }else{
                //4.如果上锁失败，就休眠 0.1s，再抢占资源
                System.out.println("上锁失败！开始休眠！");
                try {
                    Thread.sleep(100);
                    plusRedisCount(proId);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }else {
            //如果不存在，set一个
            Product product1 = productMapper.selectById(proId);
            redisTemplate.opsForValue().set(dataKey,product1);
        }
    }

}
